package org.example.config.i18nconfig;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * MyBatis查询参数国际化拦截器
 *
 * 功能：
 * 1. 拦截MyBatis查询操作
 * 2. 自动识别查询参数中需要反向翻译的字段
 * 3. 将多语言查询条件转换为数据库中的中文原文
 * 4. 支持注解标记和命名规则识别
 *
 *
 */
@Slf4j
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class I18nQueryInterceptor implements Interceptor {

    @Resource
    private I18nReverseTranslateUtils reverseTranslateUtils;

    // 需要进行反向翻译的字段名模式
    private static final Set<String> TRANSLATABLE_FIELD_PATTERNS = Set.of(
            "dsc"
//            "name", "title", "description", "content", "label", "text"
    );

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameter = args[1];

        // 只处理查询操作
        if (isSelectStatement(ms) && hasI18nQueryMethodAnnotation(ms)) {
            Object processedParameter = processQueryParameter(parameter, ms);
            if (processedParameter != parameter) {
                args[1] = processedParameter;
                log.debug("查询参数反向翻译处理完成: {}", ms.getId());
            }
        }

        return invocation.proceed();
    }
    /**
     * 检查方法是否有@I18nQueryMethod注解
     */
    private boolean hasI18nQueryMethodAnnotation(MappedStatement ms) {
        try {
            String mapperMethod = ms.getId();
            int lastDotIndex = mapperMethod.lastIndexOf('.');
            if (lastDotIndex == -1) return false;

            String className = mapperMethod.substring(0, lastDotIndex);
            String methodName = mapperMethod.substring(lastDotIndex + 1);

            // 已加载则直接返回）
            Class<?> mapperClass = Class.forName(className, false, getClass().getClassLoader());
            // 查找匹配的方法（不限制参数类型）
            for (Method method : mapperClass.getMethods()) {
                if (method.getName().equals(methodName)) {
                    // 找到匹配方法名的方法
                    return method.isAnnotationPresent(I18nQueryMethod.class);
                }
            }
            return false;
        } catch (Exception e) {
            log.warn("检查方法注解失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 处理查询参数，进行反向翻译
     */
    private Object processQueryParameter(Object parameter, MappedStatement ms) {
        if (parameter == null) {
            return parameter;
        }

        try {
            // 处理不同类型的参数
            if (parameter instanceof Map) {
                return processMapParameter((Map<String, Object>) parameter);
            } else if (parameter instanceof String) {
                return reverseTranslateUtils.reverseTranslate((String) parameter);
            } else if (isCustomObject(parameter)) {
                return processObjectParameter(parameter);
            }
        } catch (Exception e) {
            log.warn("查询参数反向翻译处理失败: {}, error: {}", ms.getId(), e.getMessage());
        }

        return parameter;
    }

    /**
     * 处理Map类型参数
     */
    private Map<String, Object> processMapParameter(Map<String, Object> paramMap) {
        Map<String, Object> processedMap = new HashMap<>(paramMap);

        for (Map.Entry<String, Object> entry : processedMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value instanceof String && shouldTranslateField(key)) {
                String originalValue = (String) value;
                String translatedValue;
                // 检查是否为模糊查询格式（%开头且%结尾）
                if (originalValue.startsWith("%") && originalValue.endsWith("%") && originalValue.length() > 2) {
                    // 提取中间需要翻译的部分
                    String contentToTranslate = originalValue.substring(1, originalValue.length() - 1);
                    // 只翻译中间内容
                    String translatedContent = reverseTranslateUtils.reverseTranslate(contentToTranslate);
                    // 保留前后的%符号
                    translatedValue = "%" + translatedContent + "%";
                } else {
                    // 非模糊查询格式，正常翻译整个值
                    translatedValue = reverseTranslateUtils.reverseTranslate(originalValue);
                }

                if (!translatedValue.equals(originalValue)) {
                    processedMap.put(key, translatedValue);
                    log.debug("Map参数反向翻译: {} = {} -> {}", key, originalValue, translatedValue);
                }
            } else if (isCustomObject(value)) {
                processedMap.put(key, processObjectParameter(value));
            } else if (value instanceof Map) { // 递归处理嵌套的Map
                Map<String, Object> nestedMap = (Map<String, Object>) value;
                Map<String, Object> processedNestedMap = processMapParameter(nestedMap);  // 递归调用
                if (processedNestedMap != nestedMap) {
                    processedMap.put(key, processedNestedMap);
                }
            }
        }

        return processedMap;
    }

    /**
     * 处理自定义对象参数
     */
    private Object processObjectParameter(Object obj) {
        if (obj == null) {
            return obj;
        }

        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            boolean hasChanges = false;

            for (Field field : fields) {
                if (shouldTranslateField(field)) {
                    field.setAccessible(true);
                    Object value = field.get(obj);

                    if (value instanceof String) {
                        String originalValue = (String) value;
                        String translatedValue = reverseTranslateUtils.reverseTranslate(originalValue);

                        if (!translatedValue.equals(originalValue)) {
                            field.set(obj, translatedValue);
                            hasChanges = true;
                            log.debug("对象字段反向翻译: {}.{} = {} -> {}",
                                    clazz.getSimpleName(), field.getName(), originalValue, translatedValue);
                        }
                    }
                }
            }

            if (hasChanges) {
                log.debug("对象参数反向翻译完成: {}", clazz.getSimpleName());
            }

        } catch (Exception e) {
            log.warn("处理对象参数失败: {}", e.getMessage());
        }

        return obj;
    }

    /**
     * 判断字段是否需要反向翻译（基于注解）
     */
    private boolean shouldTranslateField(Field field) {
        // 检查是否有@I18nQueryField注解
        if (field.isAnnotationPresent(I18nQueryField.class)) {
            return true;
        }

        // 检查字段名是否匹配模式
        return shouldTranslateField(field.getName());
    }

    /**
     * 判断字段是否需要反向翻译（基于字段名）
     */
    private boolean shouldTranslateField(String fieldName) {
        if (fieldName == null) {
            return false;
        }

        String lowerFieldName = fieldName.toLowerCase();

        // 精确匹配
        if (TRANSLATABLE_FIELD_PATTERNS.contains(lowerFieldName)) {
            return true;
        }

        // 包含匹配
        return TRANSLATABLE_FIELD_PATTERNS.stream()
                .anyMatch(pattern -> lowerFieldName.contains(pattern));
    }

    /**
     * 判断是否为查询语句
     */
    private boolean isSelectStatement(MappedStatement ms) {
        return ms.getSqlCommandType().name().equals("SELECT");
    }

    /**
     * 判断是否为自定义对象
     */
    private boolean isCustomObject(Object obj) {
        if (obj == null) {
            return false;
        }

        Class<?> clazz = obj.getClass();
        Package pkg = clazz.getPackage();

        // 排除基本类型和常见框架类
        return pkg != null && !pkg.getName().startsWith("java.") && !pkg.getName().startsWith("org.springframework.")
                && !clazz.isPrimitive() && !clazz.isEnum();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以通过配置文件设置拦截器属性
        log.info("I18nQueryInterceptor initialized with properties: {}", properties);
    }
}